﻿
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace CNative.Dapper.Utils
{
    /// <summary>
    /// 写日志类
    /// </summary>
    public class LogUtil
    {
        #region 字段

        private static Mutex _mutexDebug = new Mutex(false, "LogUtil.Mutex.Debug.252F8025254D4DAA8EFB7FFE177F13E0");
        private static Mutex _mutexInfo = new Mutex(false, "LogUtil.Mutex.Info.180740C3B1C44D428683D35F84F97E22");
        private static Mutex _mutexError = new Mutex(false, "LogUtil.Mutex.Error.81273C1400774A3B8310C2EC1C3AFFFF");
        private static Mutex _mutexWarn = new Mutex(false, "LogUtil.Mutex.Warn.81273C1400774A3B8310C2EC1C3AFFFF");
        private static Mutex _mutexFatal = new Mutex(false, "LogUtil.Mutex.Fatal.81273C1400774A3B8310C2EC1C3AFFFF");
        private static Mutex _mutexLog = new Mutex(false, "LogUtil.Mutex.Log.81273C1400774A3B8310C2EC1C3AFFFF");

        private static TaskSchedulerEx _scheduler = new TaskSchedulerEx(2, 2);
        private static ConcurrentDictionary<string, FgLogHelperPro> _dictLogHelperPro
            = new ConcurrentDictionary<string, FgLogHelperPro>();
        public static string BaseDirectory
        {
            get
            {
                string location = AppDomain.CurrentDomain.BaseDirectory.Substring(0, AppDomain.CurrentDomain.BaseDirectory.LastIndexOf('\\'));
                return location;
            }
        }
        static string _configfile = @"\LogNetConfig.config";
        static System.IO.FileInfo configFileInfo = null;
        #endregion

        #region LogUtil
        /// <summary>
        /// 初始化对象
        /// </summary>
        static LogUtil()
        {
            try
            {
                _configfile = BaseDirectory + @"\LogNetConfig.config";
                configFileInfo = new System.IO.FileInfo(_configfile);
                log4net.Config.XmlConfigurator.Configure(configFileInfo);
                //XmlGetElement(configFileInfo.FullName);
                try
                {
                    LogSaveday = Convert.ToInt32(FgFuncStr.GetAppSettingsVal("LogSaveday", "30"));
                }
                catch { LogSaveday = 30; }
                DelDirectorys(BaseDirectory + @"\Log", LogSaveday);
            }
            catch { }
        }
        #endregion

        #region 写调试日志
        /// <summary>
        /// 写调试日志
        /// </summary>
        public static void Debug(string log)
        {
            if (string.IsNullOrWhiteSpace(log))
                return;
            Task.Factory.StartNew(() =>
            {
                try
                {
                    _mutexDebug.WaitOne();

                    var logKey = "Debug";
                    GetLogHelperPro(logKey)?.Write.Debug(log);

                    //log = CreateLogString(LogType.Debug, log);
                    //string path = CreateLogPath(LogType.Debug, log);
                    //WriteFile(LogType.Debug, log, path);

                    if (Environment.UserInteractive)
                    {
                        WriteText(log, ConsoleColor.Green);
                        WriteLinetext();
                    }
                }
                catch (Exception ex)
                {
                    string str = ex.Message;
                }
                finally
                {
                    _mutexDebug.ReleaseMutex();
                }
            }, CancellationToken.None, TaskCreationOptions.None, _scheduler);
        }
        #endregion

        #region 写错误日志
        public static void Error(Exception ex, string log = null)
        {
             Error(string.IsNullOrEmpty(log) ? ex.Message + "\r\n" + ex.StackTrace : (log + "：") + ex.Message + "\r\n" + ex.StackTrace);
        }

        /// <summary>
        /// 写错误日志
        /// </summary>
        public static void Error(string log)
        {
            if (string.IsNullOrWhiteSpace(log))
                return ;
            Task.Factory.StartNew(() =>
            {
                try
                {
                    _mutexError.WaitOne();

                    var logKey = "Error";
                    GetLogHelperPro(logKey)?.Write.Error(log);

                    //log = CreateLogString(LogType.Error, log);
                    //string path = CreateLogPath(LogType.Error, log);
                    //WriteFile(LogType.Error, log, path);

                    if (Environment.UserInteractive)
                    {
                        WriteText(log, ConsoleColor.Red);
                        WriteLinetext();
                    }
                }
                catch (Exception ex)
                {
                    string str = ex.Message;
                }
                finally
                {
                    _mutexError.ReleaseMutex();
                }
            }, CancellationToken.None, TaskCreationOptions.None, _scheduler);
        }
        #endregion
        #region 写严重日志
        /// <summary>
        /// 写严重日志
        /// </summary>
        /// <param name="log"></param>
        /// <returns></returns>
        public static void Fatal(string log)
        {
            if (string.IsNullOrWhiteSpace(log))
                return ;
            Task.Factory.StartNew(() =>
            {
                try
                {
                    _mutexFatal.WaitOne();

                    var logKey = "Fatal";
                    GetLogHelperPro(logKey)?.Write.Fatal(log);

                    if (Environment.UserInteractive)
                    {
                        WriteText(log, ConsoleColor.DarkYellow);
                        WriteLinetext();
                    }
                }
                catch (Exception ex)
                {
                    string str = ex.Message;
                }
                finally
                {
                    _mutexFatal.ReleaseMutex();
                }
            }, CancellationToken.None, TaskCreationOptions.None, _scheduler);
        }
        #endregion
        #region 写警告日志
        /// <summary>
        /// 写警告日志
        /// </summary>
        /// <param name="log"></param>
        /// <returns></returns>
        public static void Warn(string log)
        {
            if (string.IsNullOrWhiteSpace(log))
                return ;
            Task.Factory.StartNew(() =>
            {
                try
                {
                    _mutexWarn.WaitOne();

                    var logKey = "Warn";
                    GetLogHelperPro(logKey)?.Write.Warn(log);

                    if (Environment.UserInteractive)
                    {
                        WriteText(log, ConsoleColor.Yellow);
                        WriteLinetext();
                    }
                }
                catch (Exception ex)
                {
                    string str = ex.Message;
                }
                finally
                {
                    _mutexWarn.ReleaseMutex();
                }
            }, CancellationToken.None, TaskCreationOptions.None, _scheduler);
        }
        #endregion

        #region 写信息日志
        /// <summary>
        /// 写信息
        /// </summary>
        /// <param name="log"></param>
        /// <returns></returns>
        public static void Info(string log)
        {
            if (string.IsNullOrWhiteSpace(log))
                return ;
            Task.Factory.StartNew(() =>
            {
                try
                {
                    _mutexInfo.WaitOne();

                    var logKey = "Info";
                    GetLogHelperPro(logKey)?.Write.Info(log);

                    if (Environment.UserInteractive)
                    {
                        WriteText(log, ConsoleColor.White);
                        WriteLinetext();
                    }
                }
                catch (Exception ex)
                {
                    string str = ex.Message;
                }
                finally
                {
                    _mutexInfo.ReleaseMutex();
                }
            }, CancellationToken.None, TaskCreationOptions.None, _scheduler);
        }
        #endregion

        #region 写操作日志
        /// <summary>
        /// 获取写日志类
        /// </summary>
        /// <param name="logKey"></param>
        /// <returns></returns>
        internal static FgLogHelperPro GetLogHelperPro(string _FileName)
        {
            if (!_dictLogHelperPro.TryGetValue(_FileName, out var logHelperPro))
            {
                logHelperPro = new FgLogHelperPro(_FileName);
                _dictLogHelperPro.TryAdd(_FileName, logHelperPro);
            }
            return logHelperPro;
        }
        /// <summary>
        /// 写操作日志
        /// </summary>
        public static void Log(string _FileName, string log, Exception exception = null, ConsoleColor color = ConsoleColor.Gray)
        {
            if (string.IsNullOrWhiteSpace(log))
                return ;
            Task.Factory.StartNew(() =>
            {
                try
                {
                    _mutexLog.WaitOne();

                    if (exception == null)
                        GetLogHelperPro(_FileName)?.Write.Error(log);
                    else
                        GetLogHelperPro(_FileName)?.Write.Error(log, exception);

                    //log = CreateLogString(LogType.Info, log);
                    //string path = CreateLogPath(LogType.Info, log);
                    //WriteFile(LogType.Info, log, path);

                    if (exception != null && Environment.UserInteractive)
                    {
                        WriteText(log, ConsoleColor.Red);
                        WriteLinetext();
                    }
                }
                catch (Exception ex)
                {
                    string str = ex.Message;
                }
                finally
                {
                    _mutexLog.ReleaseMutex();
                }
            }, CancellationToken.None, TaskCreationOptions.None, _scheduler);
        }
        #endregion

        #region Console set
        private static bool setConsoleColor = false;
        /// <summary>
        /// 判断能否设置控制台字体颜色
        /// </summary>
        public static void CheckCanSetConsoleColor()
        {
            try
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.ResetColor();
                setConsoleColor = true;
            }
            catch
            {
                setConsoleColor = false;
            }
        }
        /// <summary>
        /// 设置控制台字体颜色
        /// </summary>
        /// <param name="color"></param>
        public static void SetConsoleColor(ConsoleColor color)
        {
            try
            {
                Console.ForegroundColor = color;
                setConsoleColor = true;
            }
            catch
            {
                setConsoleColor = false;
            }
            //if (setConsoleColor)
            //   Console.ForegroundColor = color;
        }
        public static void WriteText(ConsoleColor color, string format, params object[] arg)
        {
            try
            {
                SetConsoleColor(color);
                Console.WriteLine(format, arg);
                Console.ResetColor();
            }
            catch { WriteText(format, color); }
        }
        public static void WriteText(string txt, ConsoleColor color)
        {
            try
            {
                SetConsoleColor(color);
                Console.WriteLine(txt);
                Console.ResetColor();
            }
            catch { }
        }
        /// <summary>
        /// 画控制台线
        /// </summary>
        public static void WriteLinetext(string line = "--------------------------------------------------------------------------------------------------")
        {
            try
            {
                Console.ResetColor();
                Console.WriteLine(line);
            }
            catch { }
        }
        #endregion

        #region 删指定文件夹里的文件
        /// <summary>
        /// 日志保留天数
        /// </summary>
        public static int LogSaveday { get; set; } = 30;
        /// <summary>
        /// 删除指定文件夹里的文件
        /// </summary>
        public static void DelDirectorys()
        {
            DelDirectorys(@"log\", LogSaveday);
        }
        /// <summary>
        /// 删除指定文件夹里的文件
        /// </summary>
        public static void DelDirectorys(int diffDays)
        {
            DelDirectorys(@"log\", diffDays);
        }
        /// <summary>
        /// 删除指定文件夹里的文件
        /// </summary>
        /// <param name="FileFolder"></param>
        /// <param name="days"></param>
        public static void DelDirectorys(string FileFolder, int diffDays)
        {
            if (!System.IO.Directory.Exists(FileFolder)) return;
            try
            {
                if (diffDays < 1)
                    diffDays = 1;
                //创建DirectoryInfo实例
                var dirInfo = new DirectoryInfo(FileFolder);
                //取得源文件夹下的所有子文件夹名称
                var dirs = dirInfo.GetDirectories();
                foreach (var dir in dirs)
                {
                    //获取所有子文件夹名
                    try
                    {
                        var dirss = dir.GetDirectories();
                        if (dirss != null && dirss.Length > 0)
                        {
                            foreach (var dirsss in dirss)
                            { DelDirectorys(dirsss.FullName, diffDays); }
                        }
                        //-------------------------------------------------------------------------------------
                        DelFiles(dir.FullName, diffDays);
                        if (Math.Abs((System.DateTime.Now - dir.LastWriteTime).Days) >= diffDays || dir.GetFiles().Length == 0)
                        {
                            try
                            {
                                dir.Delete(true);
                            }
                            catch (Exception ex)
                            {
                                Error(ex.ToString());
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Error(ex.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                Error(ex.ToString());
            }
        }
        /// <summary>
        /// 删除指定文件夹里的文件
        /// </summary>
        /// <param name="FileFolder"></param>
        /// <param name="days"></param>
        public static void DelFiles(string FileFolder, int diffDays)
        {
            if (!System.IO.Directory.Exists(FileFolder)) return;
            try
            {
                //创建数组保存源文件夹下的文件名
                var dirInfo = new DirectoryInfo(FileFolder);
                var strFiles = dirInfo.GetFiles();

                foreach (var file in strFiles)
                {
                    try
                    {
                        if (Math.Abs((System.DateTime.Now - file.LastWriteTime).Days) >= diffDays)
                        {
                            file.Delete();
                        }
                    }
                    catch (Exception ex)
                    {
                        Error(ex.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                Error(ex.ToString());
            }
        }
        #endregion
    }

}
